<?php

use think\captcha\Captcha;
use think\Db;
use think\Loader;

// 异常错误报错级别,
error_reporting(E_ERROR | E_PARSE);

function C($name)
{
    $config = cache('systemConfig');
    if ($config) {
        $value = '';
        foreach ($config as $v) {
            if ($v['name'] == $name) {
                $value = $v['output_value'];
                break;
            }
        }

        return $value;
    } else {
        return Db::name('mini_config')->where(['name' => $name])->order('sort asc')->value('value');
    }
}

/**
 * 系统加密方法
 * @param string $data   要加密的字符串
 * @param int    $expire 过期时间 (单位:秒)
 * @return string
 */
function thinkEncrypt($data, $expire = 0)
{
    $key = md5('083d9a270e6e16b2fbb08d35067aae5f');
    $data = base64_encode($data);
    $x = 0;
    $len = strlen($data);
    $l = strlen($key);
    $char = '';
    for ($i = 0; $i < $len; $i++) {
        if ($x == $l) $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }
    $str = sprintf('%010d', $expire ? $expire + time() : 0);
    for ($i = 0; $i < $len; $i++) {
        $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256);
    }

    return str_replace('=', '', base64_encode($str));
}

/**
 * 系统解密方法
 * @param string $data 要解密的字符串 （必须是think_encrypt方法加密的字符串）
 * @return string
 */
/*function thinkDecrypt($data)
{
    $key = md5('083d9a270e6e16b2fbb08d35067aae5f');
    $x = 0;
    $data = base64_decode($data);
    $expire = substr($data, 0, 10);
    $data = substr($data, 10);
    if ($expire > 0 && $expire < time()) {
        return '';
    }
    $len = strlen($data);
    $l = strlen($key);
    $char = $str = '';
    for ($i = 0; $i < $len; $i++) {
        if ($x == $l) $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }
    for ($i = 0; $i < $len; $i++) {
        if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1))) {
            $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
        } else {
            $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
        }
    }

    return base64_decode($str);
}*/

/**
 * 检查验证码
 * */
function checkVerify($code)
{
    $verify = new Captcha();

    return $verify->check($code);
}

/**
 * 判断是否SSL协议
 * @return boolean
 */
function is_ssl()
{
    if (isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))) {
        return true;
    } else if (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) {
        return true;
    }

    return false;
}

/**
 * 获取域名前缀
 * */
function getHost()
{
    $res = is_ssl();
    if ($res) {
        return 'https://' . $_SERVER['HTTP_HOST'];
    } else {
        return 'http://' . $_SERVER['HTTP_HOST'];
    }
}

/**
 * 按综合方式输出通信数据
 * @param integer $result 状态码
 * @param string  $msg    提示信息
 * @param array   $data   数据
 * @return string
 */
function apiReturn($result, $msg = '', $data = false)
{
    if (!is_numeric($result)) {
        return '';
    }

    return apiJson($result, $msg, $data);
}

/**
 * 按json方式输出通信数据
 * @param integer $result 状态码
 * @param string  $msg    提示信息
 * @param array   $data   数据
 * @return string
 */
function apiJson($result, $msg = '', $data = false)
{

    if (!is_numeric($result)) {
        return '';
    }

    if ($data > 0 || $data === []) {
        $message = [
            'result' => $result,
            'msg' => $msg,
            'data' => $data ? : []
        ];
    } else {
        $message = [
            'result' => $result,
            'msg' => $msg,
            'data' => $data ? : ''
        ];
    }

    echo json_encode($message, JSON_UNESCAPED_UNICODE);
    exit;
}

/**
 * 根据图片id获取图片路径
 * */
function getPicture($id)
{
    if (preg_replace('/\D/s', '', $id) == $id) {
        //ID
        $info = Db::name('mini_picture')->field('path')->where(['id' => $id])->find();
        if ($info) {
            return getHost() . $info['path'];
        } else {
            return '';
        }
    } else {
        //路径
        return getHost() . $id;
    }
}

/**
 * 金额拆分处理
 * */
function doPrice($price)
{
    // 格式化金额，确保有两位小数
    $formattedAmount = number_format((float)$price, 2, '.', '');

    // 拆分整数部分和小数部分
    list($integerPart, $decimalPart) = explode('.', $formattedAmount);

    return [
        'integer' => $integerPart,
        'decimal' => $decimalPart
    ];
}

/**
 * 图片路径处理
 * @param int $avatar 用户头像路径
 * @return string
 * */
function doImgPath($avatar)
{
    return $avatar ? getHost() . $avatar : '';
}

/**
 * 多图处理
 * @param string $imgs    图片id集合
 * @param string $img_key 自定义图片路径下标
 * @return array
 * */
function doImgs($imgs, $img_key = 'path')
{
    $new_img_arr = [];
    if ($imgs) {
        $img_arr = explode(',', $imgs);

        if ($img_arr) {
            foreach ($img_arr as $k => $v) {
                $new_img_arr[$k]['id'] = $v;
                $new_img_arr[$k][$img_key] = getPicture($v);
            }
        }
    }

    return $new_img_arr;
}

/**
 * 获取[规格-属性]数据
 * @param int $goods_id 商品id
 * @return array
 * */
function getSku($goods_id)
{
    $sku_value_list = Db::name('mini_sku_value')->where(['goods_id' => $goods_id])->select();

    //$skus_id_arr：所有属性的id集合
    $skus_id_arr = [];
    $sku_list = [];
    if ($sku_value_list) {
        foreach ($sku_value_list as &$val) {
            $val['img'] = getPicture($val['img']);

            $sku_id = explode('-', $val['sku_id']);
            if ($sku_id) {
                foreach ($sku_id as $value) {
                    if (!in_array($value, $skus_id_arr)) {
                        $skus_id_arr[] = $value;
                    }
                }
            }
        }

        $parent_list = Db::name('mini_goods_sku')->distinct(true)->field('pid')->where(['id' => ['IN', $skus_id_arr]])->select();
        $parent_ids = array_column((array)$parent_list, 'pid');
        if ($parent_ids) {
            $sku_list = Db::name('mini_goods_sku')->field('id,name title')->where(['id' => ['IN', $parent_ids]])->select();
            if ($sku_list) {
                foreach ($sku_list as &$v) {
                    $child_list = Db::name('mini_goods_sku')->field('id,name title')->where(['pid' => $v['id']])->select();
                    if ($child_list) {
                        foreach ($child_list as &$val) {
                            $val['class'] = '';
                            $val['status'] = false;
                            foreach ($sku_value_list as $value) {
                                if (in_array($val['id'], explode('-', $value['sku_id'])) && $value['status']) {
                                    $val['status'] = true;
                                    break;
                                }
                            }
                        }
                    } else {
                        $child_list = [];
                    }
                    $v['child'] = $child_list;
                }
            } else {
                $sku_list = [];
            }
        }
    } else {
        $sku_value_list = [];
    }

    $data = [
        'sku_list' => $sku_list,
        'sku_value_list' => $sku_value_list
    ];

    return $data;
}

/**
 * 微信违规文字检测
 * */
function checkContent($content)
{
    if ($access_token = accessToken()) {
        $checkUrl = 'https://api.weixin.qq.com/wxa/msg_sec_check?access_token=' . $access_token;
        $arr = [
            'content' => $content
        ];

        $result = httpRequest($checkUrl, $arr, 'json');
        $result = json_decode($result, true);

        if ($result['errcode'] != 0) apiReturn(2, '检测到文字含违规内容，请重新编辑');
    } else {
        apiReturn(2, 'access_token获取失败');
    }
}

function accessToken()
{
    $appid = C('XCX_APPID');
    $secret = C('XCX_SECRET');
    $tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $secret;
    $tokenArr = file_get_contents($tokenUrl);
    $tokenArr = json_decode($tokenArr, true);

    return $tokenArr['access_token'];
}

function httpRequest($url, $data, $type)
{
    if ($type == 'json') {
        $headers = ["Content-type: application/json;charset=UTF-8", "Accept: application/json", "Cache-Control: no-cache", "Pragma: no-cache"];
        $data = json_encode($data, JSON_UNESCAPED_UNICODE);
    } else {
        $headers = [];
    }
    $curl = getCurl($url, $data);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    $output = curl_exec($curl);
    curl_close($curl);

    return $output;
}

/**
 * @param $url
 * @param $data
 * @return false|resource
 */
function getCurl($url, $data = null, $header = null)
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
    if (!empty($data)) {
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    }
    // 设置header头
    if (!empty($header)) curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    return $curl;
}

/**
 * 一维数组去重
 * */
function a_array_unique($array)
{
    $out = [];
    foreach ($array as $key => $value) {
        if (!in_array($value, $out)) {
            $out[$key] = $value;
        }
    }

    return $out;
}

/**
 * 处理富文本信息
 * @param string $content 富文本内容
 * @return  string
 * */
function doEditorContent($content)
{
    return $content ? str_replace('<img src="', ' <img style = "width: 100%; height: auto" src = "' . getHost(), $content) : '';
}

/**
 * 格式化时间
 * @param int  $time 时间戳
 * @param date $date 时间格式
 * */
function timeFormat($time, $date = 'Y-m-d H:i:s')
{
    if ($time) {
        return date($date, $time);
    } else {
        return '';
    }
}

/**
 * @param array $sku_id 属性id集合
 * @return string
 * */
function getSkuName($sku_id)
{
    if ($sku_id) {
        $in_sku = implode(',', $sku_id);
        $order = ' field (id, ' . $in_sku . ' ) ';
        $sql = 'SELECT `name` FROM `fa_mini_goods_sku` WHERE `id` IN(' . $in_sku . ') ORDER BY ' . $order;
        return Db::query($sql);
    } else {
        return '';
    }
}

/**
 * 获取省id
 * @param string $province_name 省名称
 * @return int
 * */
function getProvinceId($province_name)
{
    return Db::name('mini_province')->where(['name' => $province_name])->value('province_id');
}

/**
 * 获取省名称
 * @param int $province_id 省id
 * @return string
 * */
function getProvinceName($province_id)
{
    $name = Db::name('mini_province')->where(['province_id' => $province_id])->value('name');

    return $name ? : '';
}

/**
 * 获取市id
 * @param string $province_name 省名称
 * @param string $city_name     市名称
 * @return int
 * */
function getCityId($province_name, $city_name)
{
    $province_id = getProvinceId($province_name);

    $city_name = str_replace(['市', '省'], '', $city_name);
    return Db::name('mini_city')->where(['province_id' => $province_id, 'name' => ['like', $city_name . '%']])->value('city_id');
}

/**
 * 获取市名称
 * @param int $city_id 市id
 * @return string
 * */
function getCityName($city_id)
{
    $name = Db::name('mini_city')->where(['city_id' => $city_id])->value('name');

    return $name ? : '';
}

/**
 * 获取区id
 * @param string $province_name 省名称
 * @param string $city_name     市名称
 * @param string $area_name     市名称
 * @return int
 * */
function getAreaId($province_name, $city_name, $area_name)
{
    $city_id = getCityId($province_name, $city_name);

    $area_name = str_replace(['市', '区', '县'], '', $area_name);
    return Db::name('mini_area')->where(['city_id' => $city_id, 'name' => ['like', $area_name . '%']])->value('area_id');
}

/**
 * 获取区名称
 * @param int $area_id 区id
 * @return string
 * */
function getAreaName($area_id)
{
    $name = Db::name('mini_area')->where(['area_id' => $area_id])->value('name');

    return $name ? : '';
}

function httpsRequest($url, $data = null, $header = null)
{
    $curl = getCurl($url, $data, $header);
    $output = curl_exec($curl);
    curl_close($curl);

    return $output;
}

/**
 * 获取access_token
 * @return string
 *  */
function getAccessToken(&$count = 0)
{
    $config = [
        'appid' => C('XCX_APPID'),
        'secret' => C('XCX_SECRET'),
    ];

    // access_token 应该全局存储与更新，以下代码以写入到文件中做示例
    $data = json_decode(get_php_file('access_token.json'));
    if ($data->expires_time < time()) {
        // 如果是企业号用以下URL获取access_token
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $config['appid'] . "&secret=" . $config['secret'];
        $access_token_json = httpsRequest($url);
        $access_token = json_decode($access_token_json, true);
        $code = $access_token['errcode'] ? : 0;
        if ($code == 0) {
            $data->expires_time = time() + 2000;
            $data->access_token = $access_token;
            set_php_file('access_token.json', json_encode($data));

            $access_token = $access_token['access_token'];
        } else {
            if ($count < 3) {
                ++$count;
                getAccessToken($count);
            } else {
                unlink(RUNTIME_PATH . '/access_token.json');
                apiReturn(2, $access_token['errmsg']);
            }
        }
    } else {
        $access_token = $data->access_token->access_token;
    }

    return $access_token;
}

function get_php_file($filename)
{
    if (!is_file(RUNTIME_PATH . '/' . $filename)) {
        $data['expires_time'] = 0;
        $data['jsapi_ticket'] = '';
        set_php_file($filename, json_encode($data));
    }

    return file_get_contents(RUNTIME_PATH . '/' . $filename);
}

function set_php_file($filename, $content)
{
    file_put_contents(RUNTIME_PATH . '/' . $filename, $content);
}

/**
 * 注册用户 及 绑定用户
 * @param array $user_data 当前用户信息
 * @return array
 * */
function bindUser($user_data)
{
    $time = time();

    $user_info = Db::name('mini_user')->where(['openid' => $user_data['openid']])->find();
    if ($user_info) {
        // 直接返回用户id和用户手机号
        $return_data = [
            'user_id' => $user_info['id'],
            'mobile' => $user_info['mobile'] ? : ''
        ];
    } else {
        // 新用户

        //注册用户信息 及 绑定
        $user_data['create_time'] = $time;

        $return_user_id = Db::name('mini_user')->insertGetId($user_data);

        $return_data = [
            'user_id' => $return_user_id,
            'mobile' => ''
        ];
    }

    return $return_data;
}

/**
 * 生成用户分享码（公众号二维码[带用户id]）
 * @param string $user_id 用户id
 * @return string
 * */
function createUserQr($user_id)
{
    $qr = Db::table('fa_user')->where(['id' => $user_id])->value('qr');
    if ($qr == 0) {
        $access_token = getAccessToken();

        $data = [
            'scene' => (string)$user_id
        ];
        $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" . $access_token;

        $img = httpsRequest($url, json_encode($data));

        $dir = './uploads/userQr/';
        if (!is_dir($dir)) mkdir($dir);

        $path = $dir . 'userQr_' . $user_id . '.png';

        file_put_contents($path, $img);
        Db::table('fa_user')->where(['id' => $user_id])->setField('qr', substr($path, 1));
    }

    return $path ? substr($path, 1) : '';
}

/**
 * 生成小程序分享链接
 * */
function createMiniShareUrl($user_id)
{
    $share_url = Db::table('fa_user')->where(['id' => $user_id])->value('share_url');
    if (!$share_url) {
        $access_token = getAccessToken();

        $url = "https://api.weixin.qq.com/wxa/genwxashortlink?access_token=" . $access_token;
        $data = [
            'page_url' => '/pages/index/index',
            'is_permanent' => true
        ];

        $res = httpsRequest($url, json_encode($data));
        $res = json_decode($res, true);
        if ($res['errcode'] == 0) Db::table('fa_user')->where(['id' => $user_id])->setField('share_url', $res['link']);
    }
}

/**
 * 隐藏手机号
 * @param string $tel 手机号
 * @return string
 * */
function hideMobile($tel)
{
    return $tel ? substr_replace($tel, '****', 3, 4) : '';
}

/**
 * 过滤文本中的emoji表情包（输出到excel文件中会导致问题）
 * @param string $text 原文本
 * @return string 过滤emoji表情包后的文本
 */
function removeEmoji($text)
{
    $len = mb_strlen($text);
    $newText = '';
    for ($i = 0; $i < $len; $i++) {
        $str = mb_substr($text, $i, 1, 'utf-8');
        if (strlen($str) >= 4) continue;//emoji表情为4个字节
        $newText .= $str;
    }

    return $newText;
}

/**
 * workerman
 * 获取后台用户列表用户最新的消息时间
 * @param int $user_id 用户id
 * @return string
 * */
function getUserNewMsgTime($user_id)
{
    $create_time = Db::name('mini_chat')
        ->where(['from_uid' => $user_id])
        ->whereOr(
            function ($query) use ($user_id) {
                $query->where(['to_uid' => $user_id]);
            }
        )
        ->order('create_time desc')
        ->value('create_time');

    return $create_time ? date('H:i:s', $create_time) : '';
}

/**
 * 获取用户的真实 IP
 * */
function getRealIp()
{
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    return $ip;
}

/**
 * 目录清单，列出所有文件和文件夹
 * @param string $dir 路径
 * */
function list_files($dir)
{
    if (is_dir($dir)) {
        if ($handle = opendir($dir)) {
            while (($file = readdir($handle)) !== false) {
                if ($file != "." && $file != ".." && $file != "Thumbs.db"/*pesky windows, images..*/) {
                    echo '<a target="_blank" href="' . $dir . $file . '">' . $file . '</a>' . "\n";
                }
            }
            closedir($handle);
        }
    }
}

/**
 * 删除文件夹内容
 * @param string $path 路径
 * */
function Delete($path)
{
    if (is_dir($path) === true) {
        $files = array_diff(scandir($path), ['.', '..']);
        foreach ($files as $file) {
            Delete(realpath($path) . '/' . $file);
        }
        return rmdir($path);
    } else if (is_file($path) === true) {
        return unlink($path);
    }
    return false;
}

/**
 * 计算两个地图坐标之间的距离
 * */
function getDistanceBetweenPointsNew($latitude1, $longitude1, $latitude2, $longitude2)
{
    $theta = $longitude1 - $longitude2;
    $miles = (sin(deg2rad($latitude1)) * sin(deg2rad($latitude2))) + (cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * cos(deg2rad($theta)));
    $miles = acos($miles);
    $miles = rad2deg($miles);
    $miles = $miles * 60 * 1.1515;
    $feet = $miles * 5280;
    $yards = $feet / 3;
    $kilometers = $miles * 1.609344;
    $meters = $kilometers * 1000;
    return compact('miles', 'feet', 'yards', 'kilometers', 'meters');
}

/**
 * 转换字节
 * @param int $bytes 传入字节数值
 * @param int $decimals
 * @return string BKMGTP
 */
function human_filesize($bytes, $decimals = 2)
{
    $sz = 'BKMGTP';
    $factor = floor((strlen($bytes) - 1) / 3);
    return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}

/**
 * 删除该目录以及该目录下面的所有文件和文件夹
 * @param string $dir 目录
 * @return bool
 */
function removeDir($dirName)
{
    //判断传入参数是否目录，如不是执行删除文件
    if (!is_dir($dirName)) {
        //删除文件
        @unlink($dirName);
    }
    //如果传入是目录，使用@opendir将该目录打开，将返回的句柄赋值给$handle
    $handle = @opendir($dirName);
    //这里明确地测试返回值是否全等于（值和类型都相同）FALSE
    //否则任何目录项的名称求值为 FALSE 的都会导致循环停止（例如一个目录名为“0”）
    while (($file = @readdir($handle)) !== false) {
        //在文件结构中，都会包含形如“.”和“..”的向上结构
        //但是它们不是文件或者文件夹
        if ($file != '.' && $file != '..') {
            //当前文件$dir为文件目录+文件
            $dir = $dirName . '/' . $file;
            //判断$dir是否为目录，如果是目录则递归调用reMoveDir($dirName)函数
            //将其中的文件和目录都删除；如果不是目录，则删除该文件
            is_dir($dir) ? removeDir($dir) : @unlink($dir);
        }
    }
    closedir($handle);
    return rmdir($dirName);
}

function getUsersName($user_ids)
{
    $list = Db::name('mini_user')->where(['id' => ['IN', $user_ids]])->select();
    $users_name = '';
    if ($list) {
        foreach ($list as &$v) {
            if ($users_name == '') {
                $users_name = $v['username'];
            } else {
                $users_name .= ',' . $v['username'];
            }
        }
    }
    return $users_name;
}

// 1：下单得积分，2：积分兑换商品，3：退款返还积分，4：（积分兑换商品）退款返还积分
function doIntegralType($type)
{
    switch ($type) {
        case 1:
            $desc = '下单得积分';
            break;
        case 2:
            $desc = '积分兑换商品';
            break;
        case 3:
            $desc = '退款返还积分';
            break;
        case 4:
            $desc = '（积分兑换商品）退款返还积分';
            break;
        case 5:
            $desc = '（积分兑换商品）取消订单返还积分';
            break;
    }
    return $desc;
}


/**
 * 生成订单号
 * */
function createOrderSn()
{
    $order_sn = 'D' . date('y') . date('m') . date('d') . date('H') . date('i') . rand(1000, 9999);
    $count = Db::name('mini_order')->where(['order_sn' => $order_sn])->count();
    if ($count > 0) {
        createOrderSn();
    } else {
        return $order_sn;
    }
}

/**
 * 处理订单状态
 * @param int $status 订单状态
 * @return string
 * */
function doOrderStatus($status)
{
    switch ($status) {
        case 1:
            $desc = '待发货';
            break;
        case 2:
            $desc = '待收货';
            break;
        case 3:
            $desc = '待评价';
            break;
        case 4:
            $desc = '已完成';
            break;
        case 5:
            $desc = '已退款';
            break;
    }
    return $desc;
}

/**
 * 处理套餐订单状态
 * @param int $status 订单状态
 * @return string
 * */
function doMealOrderStatus($status)
{
    switch ($status) {
        case 1:
            $desc = '待支付';
            break;
        case 2:
            $desc = '进行中';
            break;
        case 3:
            $desc = '已完成';
            break;
        case 4:
            $desc = '已取消';
            break;
    }
    return $desc;
}

/**
 * 处理余额类型
 * @param int $type 余额类型
 * @return string
 * */
function doBalanceType($type)
{
    switch ($type) {
        case 1:
            $desc = '充值';
            break;
        case 2:
            $desc = '购物';
            break;
        case 3:
            $desc = '退款';
            break;
    }
    return $desc;
}

/**
 * 获取用户权限区域id集合
 * */
function getUserAuthRegionIds($user_id)
{
    $sql = "select id from fa_mini_region where find_in_set(${user_id}, user_ids)";
    $region_list = Db::name('mini_region')->query($sql);

    return $region_list ? array_column($region_list, 'id') : [];
}

/**
 * 获取用户权限门店id集合
 * */
function getUserAuthShopIds($user_id)
{
    $sql = "select id from fa_mini_shop where find_in_set(${user_id}, user_ids)";
    $shop_list = Db::name('mini_shop')->query($sql);

    return $shop_list ? array_column($shop_list, 'id') : [];
}

/**
 * 获取用户拥有权限的门店
 * */
function getUserAuthShop($user_id)
{
    $shop_list = Db::name('mini_shop')->field('id')->where(['is_del' => 0])->select();
    $shop_ids = array_column($shop_list, 'id');

    return $shop_ids ? : [];
}

/**
 * 商品订单积分退还
 * */
function afterReturnIntegral($order_id)
{
    $user_id = Db::name('mini_order')->where(['id' => $order_id])->value('user_id');
    if ($user_id) {
        $time = time();

        $up_user_id = Db::name('mini_user')->where(['id' => $user_id])->value('up_user_id');

        $send_integral = 0;
        $integral_list = [];

        $share_send_integral = 0;
        $share_integral_list = [];

        Db::startTrans();
        try {
            $list = Db::name('mini_integral_log')->where(['order_id' => $order_id])->select();
            if ($list) {
                $list_ids = array_column($list, 'id');
                foreach ($list as &$v) {
                    if ($v['user_id'] == $user_id) {
                        $send_integral += $v['integral'];

                        $integral_list[] = [
                            'user_id' => $user_id,
                            'integral' => 0 - $v['integral'],
                            'type' => 7,
                            'order_id' => $v['order_id'],
                            'create_time' => $time
                        ];
                    }

                    if ($v['user_id'] == $up_user_id) {
                        $share_send_integral += $v['integral'];

                        $share_integral_list[] = [
                            'user_id' => $up_user_id,
                            'integral' => 0 - $v['integral'],
                            'type' => 8,
                            'order_id' => $v['order_id'],
                            'create_time' => $time
                        ];
                    }
                }

                Db::name('mini_integral')->where(['id' => ['IN', $list_ids]])->setField('is_return', 1);

                if ($send_integral) Db::name('mini_user')->where(['id' => $user_id])->setDec('integral', $send_integral);
                if ($integral_list) Db::name('mini_integral_log')->insertAll($integral_list);

                if ($share_send_integral) Db::name('mini_user')->where(['id' => $up_user_id])->setDec('integral', $share_send_integral);
                if ($share_integral_list) Db::name('mini_integral_log')->insertAll($share_integral_list);
            }
        } catch (\Exception $e) {
            Db::rollback();
        }
    }
}

/**
 * 获取 区域-门店 联动数据
 * */
function getRegionToShop()
{
    $region_list = Db::name('mini_region')->field('id,name')->select();
    if ($region_list) {
        foreach ($region_list as &$v) {
            $shop_list = Db::name('mini_shop')->field('id,name')->where(['is_del' => 0])->select();
            $v['shop_list'] = $shop_list ? : [];
        }
    }
    return json_encode($region_list ? : [], JSON_UNESCAPED_UNICODE);
}

/**
 * 更新用户等级
 * */
function updateUserLevel($user_id)
{
    // 修改用户等级
    $full_price_to_vip = C('FULL_PRICE_TO_VIP');
    $full_price_to_vvip = C('FULL_PRICE_TO_VVIP');
    // 套餐订单总金额
    $all_order_price = Db::name('mini_order')->where(['user_id' => $user_id, 'type' => 2])->sum('pay_price');
    if ($all_order_price >= $full_price_to_vvip) {
        // 修改用户等级为VVIP
        Db::name('mini_user')->where(['id' => $user_id])->setField('level', 3);
    } else if ($all_order_price >= $full_price_to_vip && $all_order_price < $full_price_to_vvip) {
        // 修改用户等级为VIP
        Db::name('mini_user')->where(['id' => $user_id])->setField('level', 2);
    } else if ($all_order_price < $full_price_to_vip) {
        // 修改用户等级为普通用户
        Db::name('mini_user')->where(['id' => $user_id])->setField('level', 1);
    }
}

/**
 * 处理用户等级
 * */
function doUserLevel($level)
{
    switch ($level) {
        case 1:
            $level_desc = '普通用户';
            break;
        case 2:
            $level_desc = 'VIP';
            break;
        case 3:
            $level_desc = 'VVIP';
            break;
    }
    return $level_desc;
}

/**
 * 计算两个日期相差天数
 * */
function getDays($start, $end)
{
    $datetime_start = new DateTime($start);
    $datetime_end = new DateTime($end);
    $days = $datetime_start->diff($datetime_end)->days;
    return $days;
}


/**
 * 检查用户状态
 * */
function checkUserStatus($user_id)
{
    if ($user_id) {
        $status = Db::table('fa_user')->where(['id' => $user_id])->value('status');

        return $status == 'normal';
    } else {
        return null;
    }
}

/**
 * 获取商品封面图
 * */
function getGoodsImg($goods_id)
{
    $img = Db::name('mini_goods')->where(['id' => $goods_id])->value('img');
    return getPicture($img);
}

/**
 * 获取门店名称
 * */
function getShopName($shop_id)
{
    $name = Db::name('mini_shop')->where(['id' => $shop_id])->value('name');
    return $name ? : '';
}

/**
 * 计算两个经纬度的直线距离
 * */
function distance($lat1, $lon1, $lat2, $lon2)
{
    $theta = $lon1 - $lon2;
    $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
    $dist = acos($dist);
    $dist = rad2deg($dist);
    $miles = $dist * 60 * 1.1515;

    $distance_km = $miles * 1.609344;  // 转换成公里
    $distance_m = $distance_km * 1000; // 转换成米

    if ($distance_km < 1) {
        return round($distance_m, 2) . " m";
    } else {
        return number_format($distance_km, 2) . " km";
    }
}

/**
 * 获取下单成功打印机打印内容
 * */
function getPayOrderPrinterContent($order_id)
{
    $info = Db::name('mini_order')->where(['id' => $order_id])->find();
    if ($info) {
        $goods_list = Db::name('mini_vice_order')->where(['order_id' => $order_id])->select();
        $goods_str = '';
        if ($goods_list) {
            foreach ($goods_list as &$v) {
                $suk_value_arr = explode("-", $v['sku_id']);
                $suk_name_str = "";
                foreach ($suk_value_arr as $vv) {
                    $sku_info = Db::name("mini_goods_sku")->where(["id" => $vv])->find();
                    //                $sku_p_info = Db::name("mini_sku")->where(["id" => $sku_info['pid']])->find();
                    if ($suk_name_str == '') {
                        $suk_name_str .= $sku_info['name'];
                    } else {
                        $suk_name_str .= '/' . $sku_info['name'];
                    }
                }

                $goods_price = $v['price'] * $v['count'];
                $goods_str .= "${v['name']}      ${v['price']}元            ${suk_name_str}     ${v['count']}     ${goods_price}元<BR><BR>";
            }
        }

        $order_sn = $info['order_sn'];
        $create_time = timeFormat($info['pay_time']);
        $send_type = $info['send_type'];
        $coupon_price = $info['coupon_price'];     // 优惠券优惠金额
        $add_price = $info['add_price'];           // 优惠券优惠金额
        $pay_price = $info['pay_price'];
        $get_address = $info['get_address'];
        $get_mobile = $info['get_mobile'];
        $remark = $info['remark'];
        $get_user = mb_substr($info['get_username'], 0, 1) . ($info['get_sex'] == 1 ? '先生' : '女士');
        $lottery_price = $info['lottery_price'];// 实物券抵扣金额
        $is_business = $info['is_business'];
        $arrive_time = $info['arrive_time'] ? substr($info['arrive_time'], 5) : '';

        $lottery_dk_str = '';
        $lottery_coupon_name = '';
        if ($lottery_price > 0) {
            $lottery_dk_str = "实物券抵扣金额：${coupon_price}元<BR>";
        } else {
            $lottery_coupon_name = $info['lottery_coupon_name'] ? '<BR>本单用户已使用<B>' . $info['lottery_coupon_name'] . '</B>' : '';
        }

        $arrive_title_str = '';
        if ($is_business == 1) {
            // 预订单
            $arrive_time_str = "用餐时间：${arrive_time}<BR>";
            $arrive_title_str = '预订';
        }

        switch ($send_type) {
            case 1:
                $title = "<C>" . $arrive_title_str . "外卖订单</C><BR>";
                break;
            case 2:
                $title = "<C>" . $arrive_title_str . "自提订单</C><BR>";
                break;
            case 3:
                $title = "<C>" . $arrive_title_str . "堂食订单</C><BR>";
                break;
        }

        if ($send_type == 1) {
            // 外卖订单
            $content = "${title}
---------------------------<BR>
订单编号：${order_sn}<BR>
下单时间：${create_time}<BR>
${arrive_time_str}
---------------------------<BR>
商品名称                单价   规格          数量      小计<BR>
--------------------------------<BR>
${goods_str}${lottery_coupon_name}
--------------------------------<BR>
打包费：${pack_price}元<BR>
配送费：${delivery_price}元<BR>
参与抽奖：${add_price}元<BR>
优惠券优惠金额：${coupon_price}元<BR>
${lottery_dk_str}
实付金额：${pay_price}元<BR>
--------------------------------<BR>
联系人：${get_user}<BR>
联系电话：${get_mobile}<BR>
送餐地址：${get_address}<BR>
备注：${remark}<BR>
<CUT>
                    ";
        } elseif ($send_type == 2) {
            // 自提订单
            $content = "${title}
---------------------------<BR>
订单编号：${order_sn}<BR>
下单时间：${create_time}<BR>
${arrive_time_str}
---------------------------<BR>
商品名称                单价   规格          数量      小计<BR>
--------------------------------<BR>
${goods_str}${lottery_coupon_name}
--------------------------------<BR>
打包费：${pack_price}元<BR>
配送费：${delivery_price}元<BR>
参与抽奖：${add_price}元<BR>
优惠券优惠金额：${coupon_price}元<BR>
${lottery_dk_str}
实付金额：${pay_price}元<BR>
--------------------------------<BR>
备注：${remark}<BR>
<CUT>
                    ";
        } else {
            // 堂食订单
            $content = "${title}
---------------------------<BR>
订单编号：${order_sn}<BR>
下单时间：${create_time}<BR>
${arrive_time_str}
---------------------------<BR>
商品名称                单价   规格          数量      小计<BR>
--------------------------------<BR>
${goods_str}${lottery_coupon_name}
--------------------------------<BR>
参与抽奖：${add_price}元<BR>
优惠券优惠金额：${coupon_price}元<BR>
${lottery_dk_str}
实付金额：${pay_price}元<BR>
--------------------------------<BR>
备注：${remark}<BR>
<CUT>
                    ";
        }

        return $content;
    } else {
        return '';
    }
}

function getGoodsName($goods_id)
{
    $name = Db::name('mini_goods')->where(['id' => $goods_id])->value('name');
    return $name ? : '';
}

/**
 * 判断指定时间是否在给定的时间段内
 * @param string $currentTime 当前时间，例如 '2024-05-19 13:00'
 * @param string $timeRange   时间段，例如 '2024-05-19 12:00 - 14:00'
 * @return bool 如果当前时间在时间段内则返回 true，否则返回 false
 */
function isTimeInRange($currentTime, $timeRange)
{
    // 将当前时间字符串转换为 DateTime 对象
    $currentDateTime = new DateTime($currentTime);

    // 分割时间段字符串，获取开始时间和结束时间
    list($startTime, $endTime) = explode(' - ', $timeRange);
    $startDateTime = new DateTime($startTime);
    $endDateTime = new DateTime($endTime);

    // 判断当前时间是否在时间段内
    return $currentDateTime >= $startDateTime && $currentDateTime <= $endDateTime;
}

function getAllSon($user_id, &$list = [])
{
    $user_list = Db::table('fa_expert_relation')->whereIn('up_user_id', $user_id)->column('user_id');

    if ($user_list) {
        // 递归调用，正确传递 $list
        getAllSon($user_list, $list);
    }

    // 追加新数据并去重
    $list = array_merge($list, $user_list);
    $list = array_unique($list);

    return $list;
}


/**
 * @param        $list                主表数据
 * @param string $listColumnKey       主表关联副表字段
 * @param        $query
 * @param string $newKeyName          副表数据给主表数据的下标名称
 * @param        $needOtherTableField 需要查询副表的字段名
 * @param        $linkOtherTableField 关联副表字段名
 * @param        $getIdsFun
 * @return mixed
 */
function addOtherTableDataToList($list, string $listColumnKey, $query, string $newKeyName, $needOtherTableField = 'name', $linkOtherTableField = 'id', $getIdsFun = null)
{
    if (empty($list)) {
        return $list;
    }
    if (is_object($list)) {
        $list = json_decode(json_encode($list), true);
    }
    if ($getIdsFun) {
        $ids = $getIdsFun();
    } else {
        $ids = array_column($list, $listColumnKey);
    }

    $ids = array_unique($ids);//去重
    $ids = array_filter($ids);//去非
    if (!$ids) {
        return $list;
    }
    if ($needOtherTableField != '*') {
        $fields = "$linkOtherTableField,$needOtherTableField";
        //        $fields = explode(',', $fields);
    } else {
        $fields = '*';
    }

    $query->whereIn($linkOtherTableField, $ids);
    $otherTableData = $query->field($fields)->select();
    //    $otherTableData = json_decode(json_encode($otherTableData), true);
    $hashArr = array_column($otherTableData, null, $linkOtherTableField);
    unset($item);
    foreach ($list as &$item) {
        if (strpos($needOtherTableField, ',') !== false || $needOtherTableField == '*') {
            $item[$newKeyName] = [];
        } else {
            $item[$newKeyName] = '';
        }
        if (isset($hashArr[$item[$listColumnKey]])) {
            $parent = $hashArr[$item[$listColumnKey]];
            if (strpos($needOtherTableField, ',') !== false || $needOtherTableField == '*') {
                $item[$newKeyName] = $parent;
            } else {
                $item[$newKeyName] = $parent[$needOtherTableField];
            }
        }

        //            foreach ($otherTableData as $parent) {
        //
        //                if ($parent[$linkOtherTableField] == $item[$listColumnKey]) {
        //                    if (strpos($needOtherTableField, ',') !== false || $needOtherTableField == '*') {
        //                        $item[$newKeyName] = $parent;
        //                    } else {
        //                        $item[$newKeyName] = $parent[$needOtherTableField];
        //                    }
        //
        //                    break;
        //                }
        //            }
    }
    unset($item);
    return $list;
}

/**
 * 获取密码加密后的字符串
 * @param string $password 密码
 * @param string $salt     密码盐
 * @return string
 */
function getEncryptPassword($password, $salt = '')
{
    return md5(md5($password) . $salt);
}

function isValidPhoneNumber($phone)
{
    // 适用于中国大陆手机号码格式（支持 13x、14x、15x、16x、17x、18x、19x 开头的 11 位手机号）
    $pattern = '/^1[3-9]\d{9}$/';
    return preg_match($pattern, $phone) === 1;
}

/**
 * 处理提现状态
 * */
function doWithdrawalStatus($status)
{
    switch ($status) {
        case 1:
            $desc = '已审核';
            break;
        case 2:
            $desc = '已打款';
            break;
        case 3:
            $desc = '已驳回';
            break;
        default:
            $desc = '待审核';
            break;
    }
    return $desc;
}